﻿using System;
using System.Collections.Generic;
using StockEngine.Extensions;
using StockModel;
using Utils;

namespace StockEngine.Historical
{
	public class HistoricalSystem : PropertyChangedNotifier
	{
		#region Attributes

		private readonly GroupInitializer _groupInitializer;
		private readonly QuotationDataSource _quotationDataSource;

		private HistoricalSystemState _state;

		private bool _initialized;

		#endregion

		#region Properties

		public ObservableCollection2<StockGroup> Groups { get; private set; }

		public HistoricalSystemState State
		{
			get
			{
				return _state;
			}
			set
			{
				if (_state != value)
				{
					_state = value;
					base.OnPropertyChanged("State");
				}
			}
		}

		#endregion

		#region Public Methods

		public HistoricalSystem(StockGroupDataSource stockGroupDataSource, QuotationDataSource quotationDataSource, bool enableParallel)
		{
			_groupInitializer = new GroupInitializer(stockGroupDataSource, quotationDataSource, enableParallel);
			_quotationDataSource = quotationDataSource;

			this.Groups = new ObservableCollection2<StockGroup>();
			this.State = HistoricalSystemState.Empty;
		}

		public void InitializeSystem()
		{
			if (_initialized)
			{
				throw new InvalidOperationException("The HistoricalSystem should be initialized only once. It is already initialized.");
			}

			this.Groups.AddRange(_groupInitializer.Groups);
			_initialized = true;
		}

		public List<DateTime> GetAvailableDays()
		{
			return _quotationDataSource.GetAvailableDays();
		}

		public void LoadDay(DateTime day)
		{
			this.State = HistoricalSystemState.Loading;

			if (!_initialized)
			{
				throw new InvalidOperationException("The HistoricalSystem should be initialized before starting it");
			}

			_groupInitializer.InitializeAllGroups(day);

			this.State = HistoricalSystemState.Loaded;
		}

		public void Clear()
		{
			this.State = HistoricalSystemState.Empty;
			this.RemoveStocksFromGroups();

			_initialized = false;
		}

		#endregion

		#region Private Methods

		private void RemoveStocksFromGroups()
		{
			foreach (StockGroup stockGroup in this.Groups)
			{
				stockGroup.ClearStocks();
			}

			this.Groups.Clear();
		}

		#endregion
	}
}
